package com.example.socket.handler;

import com.example.socket.codec.MessageConvertor;
import com.example.socket.core.*;
import com.example.socket.exception.DecodeException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.helpers.MessageFormatter;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * @author frank
 * 分发器抽象类，提供部分分发器实现，以简化分发器的开发
 */
public class DispatcherSupport implements Dispatcher {
    protected static final Logger logger = LoggerFactory.getLogger(DispatcherSupport.class);

    // ---- 构造方法 ----

    @Override
    public String toString() {
        return "Dispatcher [name=" + name + "]";
    }

    // ----------
    /** BEAN NAME */
    private String name;
    /** 命令注册器 */
    @Autowired
    private CommandRegister register;
    /** 消息转换器 */
    @Autowired
    private MessageConvertor convertor;
    /** 监听器列表 */
    private final ListenerSupport listenerSupport = new ListenerSupport();

    public MessageConvertor getConvertor() {
        return convertor;
    }

    @Override
    public Processor<?, ?> getProcessor(Command command) {
        return register.getProcessor(command);
    }

    @Override
    public TypeDefinition getDefinition(Command command) {
        return register.getDefinition(command);
    }

    public CommandInfo getCommand(Command command) {
        return register.getCommand(command);
    }

    @Override
    public void register(Command command, TypeDefinition definition, Processor<?, ?> processor) {
        register.register(command, definition, processor);
    }

    @Override
    public void registerInterface(Class<?> clazz) {
        register.registerInterface(clazz);
    }

    // 接收的方法部分

    @Override
    public void receive(final Message message, final Session session) {
        // 接受到信息事件
        fireReceivedMessage(message, session);
    }

    // 发送的方法部分

    @Override
    public void send(Message message, Session session) {
        //不是短连接 并且连接已经关闭
        if (session == null || (!session.isTransitory() && !session.isConnected())) {
            // SESSION 无效
            return;
        }

        // 发送信息事件
        fireSentMessage(message, session);

        if (message.isIgnore()) {
            // 消息已设置忽略标记
            return;
        }

        write(message, session);
    }

    // ----

    @Override
    public void closed(Session session) {
        if (session == null) {
            return;
        }
    }

    // Listener 相关的方法

    @Override
    public void addListener(Listener listener) {
        listener.setDispatcher(this);
        listenerSupport.addListener(listener);
    }

    @Override
    public void addListener(int index, Listener listener) {
        listener.setDispatcher(this);
        listenerSupport.addListener(index, listener);
    }

    @Override
    public void removeListener(Listener listener) {
        listenerSupport.removeListener(listener);
    }

    // 发送监听事件的相关方法

    public void fireSentMessage(Message message, Session session) {
        listenerSupport.fireSentMessage(message, session);
    }

    public void fireReceivedMessage(Message message, Session session) {
        listenerSupport.fireReceivedMessage(message, session);
    }

    // ----------------

    /**
     * 关闭连接
     * @param session
     */
    protected void close(Session session) {
        if (session != null) {
            session.close();
        }
    }

    @Override
    public Message encodeRequest(Request<?> request) {
        Header header = request.getHeader();
        Command command = request.getCommand();
        TypeDefinition definition = getDefinition(command);
        byte[] body = convertor.encode(definition.getFormat(), request.getBody(), definition.getRequest());
        if (logger.isDebugEnabled()) {
            logger.debug("[请求]{}信息体编码后结果是[{}]", command, new String(body));
        }
        return Message.valueOf(header, body);
    }

    @Override
    public Message encodeResonse(Response<?> response) {
        Header header = response.getHeader();
        Command command = response.getCommand();
        TypeDefinition definition = getDefinition(command);
        byte[] body = convertor.encode(definition.getFormat(), response.getBody(), definition.getResponse());
        if (logger.isDebugEnabled()) {
            logger.debug("回应[{}]信息体编码后结果是[{}]", command, new String(body));
        }
        return Message.valueOf(header, body);
    }

    @Override
    public Response<?> decodeResponse(Message message) {
        byte[] bytes = message.getBody();
        Command command = message.getCommand();
        TypeDefinition definition = getDefinition(command);
        Object content;
        try {
            content = convertor.decode(definition.getFormat(), bytes, definition.getResponse());
        } catch (Exception e) {
            String msg = MessageFormatter.format("回应指令[{}]解码异常", message.getCommand()).getMessage();
            throw new DecodeException(msg, e);
        }
        return Response.valueOfMessage(message, content);
    }

    /** 获取解码后的请求对象实例 */
    @Override
    public Request<?> decodeRequest(Message message) {
        byte[] bytes = message.getBody();
        Command command = message.getCommand();
        TypeDefinition definition = getDefinition(command);
        Object content;
        try {
            content = convertor.decode(definition.getFormat(), bytes, definition.getRequest());
        } catch (Exception e) {
            String msg = MessageFormatter.format("请求指令[{}]解码异常", message.getCommand()).getMessage();
            throw new DecodeException(msg, e);
        }
        return Request.valueOf(message, content);
    }

    // ---------------- 静态方法 ----------------

    /**
     * 向SESSION对于SOCKET写入数据
     * @param message
     * @param session
     */
    public static void write(Message message, Session session) {
        session.write(message);

        if (logger.isDebugEnabled()) {
            logger.debug("SESSION[{}]发送消息[{}]-[{}]", new Object[]{session.getId(), message, message.isResponse()});
        }
    }

    // ---------------- 异常返回 ----------------

    /**
     * 处理异常回应
     * @param message
     * @param ex
     */
//	public static Message identityException(Message message, ProcessingException ex) {
//		// 日志
//		if (logger.isWarnEnabled()) {
//			logger.warn("处理通信信息[{}]时发生异常", message, ex);
//		}
//		// 处理
//		return message.clearBody().changeToErrorResponse(MessageConstant.IDENTITY_EXCEPTION);
//	}
//
//	/**
//	 * 处理异常回应
//	 * @param message
//	 * @param ex
//	 */
//	public static Message parameterException(Message message, ProcessingException ex) {
//		// 日志
//		if (logger.isWarnEnabled()) {
//			logger.warn("处理通信信息[{}]时发生异常", message, ex);
//		}
//		// 处理
//		return message.clearBody().changeToErrorResponse(MessageConstant.PARAMETER_EXCEPTION);
//	}
//
//	/**
//	 * 处理异常回应
//	 * @param message
//	 * @param ex
//	 */
//	public static Message processingException(Message message, ProcessingException ex) {
//		// 日志
//		if (logger.isWarnEnabled()) {
//			logger.warn("处理通信信息[{}]时发生异常", message, ex);
//		}
//		// 处理
//		return message.clearBody().changeToErrorResponse(MessageConstant.PROCESSING_EXCEPTION);
//	}
//
//	/**
//	 * 编码异常回应
//	 * @param message
//	 * @param ex
//	 */
//	public static Message encodeException(Message message, EncodeException ex) {
//		// 日志
//		if (logger.isWarnEnabled()) {
//			logger.warn("处理通信信息[{}]时发生编码异常", message, ex);
//		}
//		// 处理
//		return message.clearBody().changeToErrorResponse(MessageConstant.ENCODE_EXCEPTION);
//	}
//
//	/**
//	 * 解码异常回应
//	 * @param message
//	 * @param session
//	 * @param ex
//	 */
//	public static Message decodeException(Message message, DecodeException ex) {
//		// 日志
//		if (logger.isWarnEnabled()) {
//			logger.warn("处理通信信息[{}]时发生解码异常", message, ex);
//		}
//		// 处理
//		return message.clearBody().changeToErrorResponse(MessageConstant.DECODE_EXCEPTION);
//	}
//
//	/**
//	 * 指令不存在的回应
//	 * @param message
//	 */
//	public static Message commandNotFound(Message message) {
//		// 日志
//		if (logger.isWarnEnabled()) {
//			logger.warn("通信信息[{}]请求的指令不存在", message);
//		}
//		// 处理
//		return message.clearBody().changeToErrorResponse(MessageConstant.COMMAND_NOT_FOUND);
//	}
//
//	/**
//	 * 指令不存在的回应
//	 * @param message
//	 * @param e 异常原因
//	 */
//	public static Message commandNotFound(Message message, SocketException e) {
//		// 日志
//		if (logger.isWarnEnabled()) {
//			logger.warn("通信信息[{}]请求的指令不存在", message, e);
//		}
//		// 处理
//		return message.clearBody().changeToErrorResponse(MessageConstant.COMMAND_NOT_FOUND);
//	}
//
//	public static Message msgSnException(Message message, MessageSnException e) {
//		// 日志
//		if (logger.isWarnEnabled()) {
//			logger.warn("通信信息[{}]请求的序列号异常", message, e);
//		}
//		// 处理
//		return message.clearBody().changeToErrorResponse(MessageConstant.MSG_SN_EXCEPTION);
//	}
//
//	/**
//	 * 未知异常的回应
//	 * @param message
//	 * @param e 异常原因
//	 * @return
//	 */
    public static Message unknownException(Message message, Exception e) {
        // 日志
        if (logger.isWarnEnabled()) {
            logger.warn("通信信息[{}]发生未知异常", message, e);
        }
        // 处理
        return message.clearBody().changeToErrorResponse(MessageConstant.UNKNOWN_EXCEPTION);
    }
}